using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FirestarterModeller.Test.BO
{
    [TestFixture]
    public class TestPrimaryKey : TestBase
    {
        [SetUp]
        public override void SetupTest()
        {
            //Runs every time that any testmethod is executed
            base.SetupTest();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
        }

        [TearDown]
        public override void TearDownTest()
        {
            //runs every time any testmethod is complete
            base.TearDownTest();
        }

        [Test]
        public void Test_InsertNewPrimaryKeyInfo()
        {
            //---------------Set up test pack-------------------
            PrimaryKeyInfo primaryKeyInfo = TestUtils.CreateUnsavedValidPrimaryKeyInfo();

            //---------------Assert Precondition----------------
            Assert.IsTrue(primaryKeyInfo.Status.IsNew);

            //---------------Execute Test ----------------------
            primaryKeyInfo.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
        }

        [Test]
        public void Test_InsertNewPrimaryKeyInfo_Invalid()
        {
            //---------------Set up test pack-------------------
            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo();

            //---------------Assert Precondition----------------
            Assert.IsTrue(primaryKeyInfo.Status.IsNew);

            //---------------Execute Test ----------------------
            try
            {
                primaryKeyInfo.Save();
                Assert.Fail("expected Err");
            }
            //---------------Test Result -----------------------
            catch (BusObjectInAnInvalidStateException ex)
            {
                StringAssert.Contains("Business Object I D' is a compulsory field and has no value", ex.Message);
            }
            Assert.IsTrue(primaryKeyInfo.Status.IsNew);
        }

        [Test]
        public void Test_DeletePrimaryKeyInfo()
        {
            //---------------Set up test pack-------------------
            PrimaryKeyInfo primaryKeyInfo = TestUtils.CreateSavedPrimaryKeyInfo();

            //---------------Assert Precondition----------------
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
            string message;
            Assert.IsTrue(primaryKeyInfo.IsDeletable(out message));

            //---------------Execute Test ----------------------
            primaryKeyInfo.MarkForDelete();
            primaryKeyInfo.Save();

            //---------------Test Result -----------------------  
            Assert.IsTrue(primaryKeyInfo.Status.IsNew);
            Assert.IsTrue(primaryKeyInfo.Status.IsDeleted);
        }

        [Test]
        public void Test_UpdatePrimaryKeyInfo()
        {
            //---------------Set up test pack-------------------
            PrimaryKeyInfo primaryKeyInfo = TestUtils.CreateSavedPrimaryKeyInfo();

            //---------------Assert Precondition----------------
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
            string message;
            Assert.IsTrue(primaryKeyInfo.IsEditable(out message));

            //---------------Execute Test ----------------------
            primaryKeyInfo.IsObjectID = false;
            primaryKeyInfo.Generated = true;

            primaryKeyInfo.Save();

            //---------------Test Result -----------------------
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
        }

        [Test]
        public void Test_LoadPrimaryKeyInfo()
        {
            //---------------Set up test pack-------------------
            PrimaryKeyInfo primaryKeyInfo = TestUtils.CreateSavedPrimaryKeyInfo();
            BusinessObjectManager.Instance.ClearLoadedObjects();

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            PrimaryKeyInfo loadedPrimaryKeyInfo = Broker.GetBusinessObject<PrimaryKeyInfo>(primaryKeyInfo.ID);

            //---------------Test Result -----------------------  
            Assert.IsFalse(loadedPrimaryKeyInfo.Status.IsNew);
            Assert.AreEqual(loadedPrimaryKeyInfo.ID, primaryKeyInfo.ID);
            //TODO: When not using memory db Assert.AreNotSame(loadedBusinessObjectInfo, businessObjectInfo);
        }

        [Test]
        public void Test_SetPrimaryKeyToBOProp_AddsPropToPrimaryKey()
        {
            //---------------Set up test pack-------------------
            BusinessObjectInfo savedBoInfo = TestUtils.CreateSavedBusinessObjectInfo();
            BusinessObjectPropertyInfo businessObjectPropertyInfo = TestUtils.CreateSavedBusinessObjectPropertyInfo(savedBoInfo);

            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo { IsObjectID = false };
            primaryKeyInfo.BusinessObject = businessObjectPropertyInfo.BusinessObject;
            //---------------Assert Precondition----------------
            Assert.IsNull(businessObjectPropertyInfo.PrimaryKeyInfo);
            //---------------Execute Test ----------------------
            businessObjectPropertyInfo.PrimaryKeyInfo = primaryKeyInfo;
            //---------------Test Result -----------------------
            IBOProp prop = businessObjectPropertyInfo.Props["PrimaryKeyInfoID"];
            Assert.AreEqual(primaryKeyInfo.PrimaryKeyID, businessObjectPropertyInfo.PrimaryKeyInfoID);
            Assert.AreSame(primaryKeyInfo, businessObjectPropertyInfo.PrimaryKeyInfo);
            Assert.IsNull(prop.PersistedPropertyValue);
            Assert.AreEqual(1, primaryKeyInfo.BusinessObjectProperties.AddedBusinessObjects.Count);
            Assert.AreEqual(1, primaryKeyInfo.BusinessObjectProperties.Count);
        }
        [Test]
        public void Test_SavePrimaryKeySavesAssociatedBOPropertiers()
        {
            //---------------Set up test pack-------------------
            BusinessObjectInfo savedBoInfo = TestUtils.CreateSavedBusinessObjectInfo();
            BusinessObjectPropertyInfo businessObjectPropertyInfo = TestUtils.CreateSavedBusinessObjectPropertyInfo(savedBoInfo);

            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo { IsObjectID = false };
            primaryKeyInfo.BusinessObject = businessObjectPropertyInfo.BusinessObject;
            businessObjectPropertyInfo.PrimaryKeyInfo = primaryKeyInfo;
            IBOProp prop = businessObjectPropertyInfo.Props["PrimaryKeyInfoID"];

            //---------------Assert Precondition----------------
            Assert.AreEqual(primaryKeyInfo.PrimaryKeyID, businessObjectPropertyInfo.PrimaryKeyInfoID);
            Assert.IsNull(prop.PersistedPropertyValue);
            Assert.AreEqual(1, primaryKeyInfo.BusinessObjectProperties.AddedBusinessObjects.Count);
            Assert.AreEqual(1, primaryKeyInfo.BusinessObjectProperties.Count);
            //---------------Execute Test ----------------------
            primaryKeyInfo.Save();
            //---------------Test Result -----------------------
            Assert.AreEqual(primaryKeyInfo.PrimaryKeyID, prop.PersistedPropertyValue);
        }
        [Test]
        public void Test_BusinessObjectPropertiesReturnsSaved()
        {
            //---------------Set up test pack-------------------
            BusinessObjectInfo savedBoInfo = TestUtils.CreateSavedBusinessObjectInfo();
            BusinessObjectPropertyInfo businessObjectPropertyInfo = TestUtils.CreateSavedBusinessObjectPropertyInfo(savedBoInfo);
            
            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo { IsObjectID = false };
            primaryKeyInfo.BusinessObject = businessObjectPropertyInfo.BusinessObject;
            businessObjectPropertyInfo.PrimaryKeyInfo = primaryKeyInfo;
            primaryKeyInfo.Save();
            BusinessObjectManager.Instance.ClearLoadedObjects();
            //---------------Assert Precondition----------------
            Assert.IsFalse(businessObjectPropertyInfo.Status.IsNew);
            Assert.IsFalse(businessObjectPropertyInfo.Status.IsDirty);
            Assert.AreEqual(1, savedBoInfo.BusinessObjectPropertyInfos.Count);
            //---------------Execute Test ----------------------
            int count = primaryKeyInfo.BusinessObjectProperties.Count;
            //---------------Test Result -----------------------
            BusinessObjectManager.Instance.ClearLoadedObjects();
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
            Assert.AreEqual(1, count);
        }

        [Test]
        public void Test_GetBusinessObjectProperties()
        {
            //---------------Set up test pack-------------------

            BusinessObjectInfo savedBoInfo = TestUtils.CreateSavedBusinessObjectInfo();
            BusinessObjectPropertyInfo businessObjectPropertyInfo = TestUtils.CreateSavedBusinessObjectPropertyInfo(savedBoInfo);
            PrimaryKeyInfo primaryKeyInfo = CreateSavedPrimaryKeyInfo(businessObjectPropertyInfo);
            BusinessObjectManager.Instance.ClearLoadedObjects();
            //---------------Assert Precondition----------------
            Assert.IsFalse(primaryKeyInfo.Status.IsNew);
            Assert.AreEqual(1, primaryKeyInfo.BusinessObjectProperties.Count);
            //---------------Execute Test ----------------------
            BusinessObjectPropertyInfo loadedBusinessObjectPropertyInfo = primaryKeyInfo.BusinessObjectProperties[0];
            //---------------Test Result -----------------------
            Assert.AreEqual(businessObjectPropertyInfo.ID, loadedBusinessObjectPropertyInfo.ID);
        }

        private static PrimaryKeyInfo CreateSavedPrimaryKeyInfo(BusinessObjectPropertyInfo businessObjectPropertyInfo)
        {
            PrimaryKeyInfo primaryKeyInfo = new PrimaryKeyInfo();
            primaryKeyInfo.IsObjectID = false;
            if (primaryKeyInfo.BusinessObjectProperties.Count == 0)
            {
                primaryKeyInfo.BusinessObject = businessObjectPropertyInfo.BusinessObject;
                businessObjectPropertyInfo.PrimaryKeyInfo = primaryKeyInfo;
            }
            primaryKeyInfo.Save();
            return primaryKeyInfo;
        }
    }
}
